﻿using CubeCube.Tile.Rule;
using CubeCube.Utils;
using CubeCube.World;
using CubeCube.World.Generator;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;

namespace CubeCube.Tile
{
    public class TileManager
    {
        public TileDefinition[] tileDefinitions;
        public CubeWorld world;
        public Chunk.Chunk chunk;

        private Tile[] tiles;
        //世界坐标
        private Dictionary<IndexPosition, DynamicTile> dynamicTiles = new Dictionary<IndexPosition, DynamicTile>();
        public DynamicTile[] DynamicTiles
        {
            get { return new List<DynamicTile>(dynamicTiles.Values).ToArray(); }
        }

        private IndexPosition offset;

        public int sizeXbits, sizeYbits, sizeZbits;
        public int sizeX,sizeY, sizeZ;
        private int sizeXBitsYBits;

        //局部坐标
        private Queue<IndexPosition> pendingTileUpdates;
        private Queue<IndexPosition> pendingTileUpdates1 = new Queue<IndexPosition>();
        private Queue<IndexPosition> pendingTileUpdates2 = new Queue<IndexPosition>();

        private bool enqueueTileUpdates = false;     //标志是否可以进行update-tile
        private bool reportTileInvalidated = false;
        private bool updateLighting = false;

        private byte[] topPositions;  //存储的是局部坐标
        //世界坐标
        private Dictionary<IndexPosition, DynamicTile> dynamicTilesTimeout = new Dictionary<IndexPosition, DynamicTile>();

        private uint ticks;

        public uint Ticks
        {
            get { return ticks; }
        }


        public TileManager(CubeWorld cubeWorld,Chunk.Chunk chunk)
        {
            this.world = cubeWorld;
            this.pendingTileUpdates = this.pendingTileUpdates1;
            this.chunk = chunk;
            this.offset = chunk.tileOffset;
        }

        public CubeWorldGenerator Generate(CubeWorldGenerator generator)
        {
            enqueueTileUpdates = false;
            reportTileInvalidated = false;
            updateLighting = false;

            ChainedWorldGenerator chained = new ChainedWorldGenerator();
            chained.AddGenertor(generator);
            chained.AddGenertor(new InternalWorldInitializationGenerator());
            chained.BindChunk(this.chunk);
            return chained;
        }

        private class InternalWorldInitializationGenerator : CubeWorldGenerator
        {
            private int generationStep;
            private int initialIterations = 100;

            public override int GetTotalCost()
            {
                return 5;
            }

            public override int GetCurrentCost()
            {
                return generationStep;
            }

            public override bool Generate(Chunk.Chunk chunk)
            {
                switch (generationStep)
                {
                    case 0:  //Add rules
                        chunk.tileManager.EnqueueTilesWithRules();
                        chunk.tileManager.enqueueTileUpdates = true;
                        generationStep++;
                        break;

                    case 1: // Update rules
                        if (chunk.tileManager.pendingTileUpdates.Count > 0 && initialIterations-- >= 0)
                            chunk.tileManager.Update(TILE_UPDATE_STEP);
                        else
                            generationStep++;
                        break;

                    case 2: // light 1
                        //TODO: 灯光
                        //LightModelAmbient.InitLuminance(world.tileManager);
                        generationStep++;
                        break;

                    case 3: // light 2
                        //TODO: 灯光
                        //LightModelLightSource.InitLuminance(world.tileManager);
                        generationStep++;
                        break;

                    case 4: //preparing
                        chunk.tileManager.updateLighting = true;
                        chunk.tileManager.reportTileInvalidated = true;

                        //TODO: nead fix
                        //world.gameplay.WorldCreated(); 
                        return true;
                }

                return false;
            }

            public override string ToString()
            {
                switch (generationStep)
                {
                    case 0: return "Adding rules";
                    case 1: return "Updating rules";
                    case 2: return "Illuminating (1/2)";
                    case 3: return "Illuminating (2/2)";
                    case 4: return "Preparing";
                }

                return "Ready";
            }
        }



        public void Save(BinaryWriter bw)
        {
            /*
             private Tile[] tiles;
        //世界坐标
        private Dictionary<IndexPosition, DynamicTile> dynamicTiles = new Dictionary<IndexPosition, DynamicTile>();

        private IndexPosition offset;

        public int sizeXbits, sizeYbits, sizeZbits;
        public int sizeX,sizeY, sizeZ;
        private int sizeXBitsYBits;

        //局部坐标
        private Queue<IndexPosition> pendingTileUpdates;
        private Queue<IndexPosition> pendingTileUpdates1 = new Queue<IndexPosition>();
        private Queue<IndexPosition> pendingTileUpdates2 = new Queue<IndexPosition>();

        private bool enqueueTileUpdates = false;     //标志是否可以进行update-tile
        private bool reportTileInvalidated = false;
        private bool updateLighting = false;

        private byte[] topPositions;  //存储的是局部坐标
        //世界坐标
        private Dictionary<IndexPosition, DynamicTile> dynamicTilesTimeout = new Dictionary<IndexPosition, DynamicTile>();

        private uint ticks; 
             
             */
            bw.Write(tiles.Length);
            for(int i = 0; i < tiles.Length; ++i)
            {
                tiles[i].Enqueued = false;
                bw.Write(tiles[i].Serialize());
            }




        }


        public void Load(BinaryReader br)
        {

        }

        public void Create(TileDefinition[] tileDefinitions, int sizeXbits, int sizeYbits, int sizeZbits)
        {
            this.sizeXbits = sizeXbits;
            this.sizeYbits = sizeYbits;
            this.sizeZbits = sizeZbits;

            sizeXBitsYBits = sizeXbits + sizeYbits;

            sizeX = 1 << sizeXbits;
            sizeY = 1 << sizeYbits;
            sizeZ = 1 << sizeZbits;
            
            tiles = new Tile[1 << (sizeXbits + sizeYbits + sizeZbits)];
            topPositions = new byte[1 << (sizeXbits + sizeZbits)];

            this.tileDefinitions = tileDefinitions;

            this.ticks = (uint)new Random().Next(0, 100);
        }

        public Tile GetTile(IndexPosition worldPos)
        {
            Debug.Assert(chunk.ContainTilePosition(worldPos));
            IndexPosition localPos = worldPos - offset;
            return tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)];
        }

        public byte GetTileType(IndexPosition worldPos)
        {
            Debug.Assert(chunk.ContainTilePosition(worldPos));
            IndexPosition localPos = worldPos - offset;
            return tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].tileType;
        }

        //根据tiletype获取tile配置
        public TileDefinition GetTileDefinition(byte type)
        {
            return tileDefinitions[type];
        }

        //通过tile-name(id)得到tile的配置
        public TileDefinition GetTileDefinitionById(string id)
        {
            for(int i = 0; i < tileDefinitions.Length; ++i)
            {
                if (tileDefinitions[i].id == id)
                    return tileDefinitions[i];
            }
            return null;
        }

        //得到最顶部的位置(世界坐標)
        public int GetTopPosition(int worldX, int worldZ)
        {
            Debug.Assert(chunk.ContainTilePosition(new IndexPosition(worldX, offset.y, worldZ)));
            int localX = worldX - offset.x;
            int localZ = worldZ - offset.z;
            return topPositions[localX | (localZ << sizeXbits)] + offset.y;
        }

        /*
         * 设置某个Pos的tile-type
         * 1.如果是动态的,先取消动态
         * 2.如果原来的tile是光源，更新光信息
         * 3.用配置初始化newtile并更新Pos位置的tile
         * 4.更新光照
         * 5.触发tile-creat-action
         * 6.更新最高点topposition
         * 7.上报失效的tile，通知sectorManager,gameplay
         */
        public void SetTileType(IndexPosition worldPos, byte type)
        {
            Debug.Assert(chunk.ContainTilePosition(worldPos));

            IndexPosition localPos = worldPos - offset;

            Tile oldTile = tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)];

            if (oldTile.Dynamic)
            {
                SetTileDynamic(worldPos, false, false, 0);
                oldTile.Dynamic = false;
            }

            if (oldTile.LightSource)
            {
                if (updateLighting)
                {
                    //TODO: 光照
                    //LightModelLightSource.UpdateLuminanceDark(this, worldPos);
                    //oldTile.LightSourceLuminance = GetTileLightSourceLuminance(worldPos);
                }
                else
                {
                    oldTile.LightSourceLuminance = 0;
                }
            }

            Tile newTile = oldTile;
            TileDefinition tileDefinition = GetTileDefinition(type);

            newTile.tileType = type;
            newTile.Energy = (byte)tileDefinition.energy;
            newTile.Destroyed = false;
            newTile.OnFire = false;
            newTile.CastShadow = tileDefinition.castShadow;
            newTile.LightSource = (tileDefinition.lightSourceIntensity > 0);
            newTile.ExtraData = 0;

            tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)] = newTile;

            if (updateLighting)
            {
                if (newTile.CastShadow != oldTile.CastShadow)
                {
                    if (newTile.CastShadow)
                    {
                        //TODO: 光照
                        //LightModelAmbient.UpdateLuminanceDark(this, worldPos);
                        //LightModelLightSource.UpdateLuminanceDark(this, worldPos);
                    }
                    else
                    {
                        //TODO: 光照
                        // LightModelAmbient.UpdateLuminanceLight(this, worldPos, newTile.AmbientLuminance);
                        // LightModelLightSource.UpdateLuminanceLight(this, worldPos, newTile.LightSourceLuminance);
                    }
                }

                //TODO: 光照
                //if (tileDefinition.lightSourceIntensity > 0)
                //    LightModelLightSource.UpdateLuminanceLight(this, worldPos, tileDefinition.lightSourceIntensity);

            }
            else
            {
                //TODO: 光照
                //if (newTile.LightSource)
                //    SetTileLightSourceLuminance(worldPos, tileDefinition.lightSourceIntensity);
            }

            ExecuteTileActions(localPos, TileActionRule.ActionType.CREATED);

            if (enqueueTileUpdates)
                EnqueueInvalidatedTileAndNearTiles(localPos);

            UpdateTopPosition(localPos, type);

            if (reportTileInvalidated)
                ReportTileInvalidated(localPos, false);
        }


        /*
         * 设置Pos位置的tile的是否为动态tile
         * 1.如果Dynamic状态一样
         *   a.如果Dynamic为true并且timeout大于0,那么重新设置timeout值
         * 2.如果Dynamic状态不一样
         *   a.如果原本Dynamic是true,将动态tile clear,以及timeout数据都清空。
         *   b.如果原本Dynamic是false,将创建新的动态tile并且设置timeout,以及添加重力组件
         *   c.上报失效的tile，通知sectorManager,gameplay
         */
        public void SetTileDynamic(IndexPosition worldPos, bool dynamic, bool useGravity, int timeout)
        {
            IndexPosition localPos = worldPos - offset;

            if (tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].Dynamic != dynamic)
            {
                if (tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].Dynamic)
                {
                    DynamicTile dynamicTile = dynamicTiles[worldPos];
                    dynamicTiles.Remove(worldPos);
                    if (dynamicTile.timeout > 0)
                        dynamicTilesTimeout.Remove(worldPos);
                    world.objectListener.DestroyObject(dynamicTile);
                    dynamicTile.Clear();
                }

                tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].Dynamic = dynamic;

                if (dynamic)
                {
                    DynamicTile dynamicTile = new DynamicTile(world, worldPos, true, 1);//TODO:gameplay world.gameplay.NextObjectId());
                    if (useGravity)
                    {
                        //TODO: 重力
                       // dynamicTile.AddComponent(new TileComponentGravity());
                    }
                    dynamicTiles[worldPos] = dynamicTile;
                    if (timeout > 0)
                    {
                        dynamicTile.timeout = timeout;
                        dynamicTilesTimeout[worldPos] = dynamicTile;
                    }

                    world.objectListener.CreateObject(dynamicTile);
                }

                if (reportTileInvalidated)
                    ReportTileInvalidated(localPos, false);
            }
            else
            {
                if (dynamic && timeout >= 0)
                    SetTileDynamicTimeout(worldPos, timeout);
            }
        }

        //设置动态tile的timeout
        public void SetTileDynamicTimeout(IndexPosition worldPos, int timeout)
        {
            IndexPosition localPos = worldPos - offset;
            if (tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].Dynamic)
            {
                DynamicTile dynamicTile = dynamicTiles[worldPos];

                if (dynamicTile.timeout > 0)
                {
                    //Dynamic tile already in the dynamicTilesTimeout dictionary, update timeout value or remove
                    //动态tile已经存在dynamicTilesTimeout字典中，只需要更新value或者remove
                    if (timeout <= 0)
                    {
                        dynamicTile.timeout = 0;
                        dynamicTilesTimeout.Remove(worldPos);
                    }
                    else
                        dynamicTile.timeout = timeout;
                }
                else if (timeout > 0)
                {
                    //Dynamic tile not in the dynamicTilesTimeout dictionary, add it
                    //不存在，赋值timeout，并且放入字典中
                    dynamicTile.timeout = timeout;
                    dynamicTilesTimeout[worldPos] = dynamicTile;
                }
            }
        }

        /*
         * 设置tile的环境光
         * 更新tile值,上报失效的tile，通知sectorManager,gameplay
         */
        public void SetTileAmbientLuminance(IndexPosition worldPos, byte luminance)
        {
            IndexPosition localPos = worldPos - offset;
            tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].AmbientLuminance = luminance;

            if (reportTileInvalidated)
                ReportTileInvalidated(localPos, true);
        }

        /*
         * 设置tile的光源值
         * 更新tile值,上报失效的tile，通知sectorManager,gameplay
         */
        public void SetTileLightSourceLuminance(IndexPosition worldPos, byte luminance)
        {
            IndexPosition localPos = worldPos - offset;
            tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].LightSourceLuminance = luminance;

            if (reportTileInvalidated)
                ReportTileInvalidated(localPos, true);
        }

        /*
         * 设置tile的extraData
         * 更新tile值,上报失效的tile，通知sectorManager,gameplay
         * 将Pos以及相邻4个放入更新队列
         */
        public void SetTileExtraData(IndexPosition worldPos, byte extraData)
        {
            IndexPosition localPos = worldPos - offset;
            tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].ExtraData = extraData;

            if (reportTileInvalidated)
                ReportTileInvalidated(localPos, false);

            if (enqueueTileUpdates)
                EnqueueInvalidatedTileAndNearTiles(localPos);
        }

        /*
         * 获取tile的extraData
         */
        public byte GetTileExtraData(IndexPosition worldPos)
        {
            IndexPosition localPos = worldPos - offset;
            return tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].ExtraData;
        }

        public bool GetTileSolid(IndexPosition worldPos)
        {
            IndexPosition localPos = worldPos - offset;
            return GetTileDefinition(tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].tileType).solid;
        }

        public bool GetTileLiquid(IndexPosition worldPos)
        {
            IndexPosition localPos = worldPos - offset;
            return GetTileDefinition(tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].tileType).liquid;
        }

        public bool GetTileBurns(IndexPosition worldPos)
        {
            IndexPosition localPos = worldPos - offset;
            return GetTileDefinition(tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].tileType).burns;
        }

        public TileDefinition.DrawMode GetTileDrawMode(IndexPosition worldPos)
        {
            IndexPosition localPos = worldPos - offset;
            return GetTileDefinition(tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].tileType).drawMode;
        }

        public bool GetTileCastShadow(IndexPosition worldPos)
        {
            IndexPosition localPos = worldPos - offset;
            return tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].CastShadow;
        }

        public bool GetTileLightSource(IndexPosition worldPos)
        {
            IndexPosition localPos = worldPos - offset;
            return tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].LightSource;
        }

        public byte GetTileAmbientLuminance(IndexPosition worldPos)
        {
            IndexPosition localPos = worldPos - offset;
            return tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].AmbientLuminance;
        }

        public byte GetTileLightSourceLuminance(IndexPosition worldPos)
        {
            IndexPosition localPos = worldPos - offset;
            return tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].LightSourceLuminance;
        }

        //仅仅是判断了位置是否合法
        public bool IsValidTile(IndexPosition worldPos)
        {
            IndexPosition localPos = worldPos - offset;
            return localPos.x >= 0 && localPos.x < sizeX && localPos.y >= 0 && localPos.y < sizeY && localPos.z >= 0 && localPos.z < sizeZ;
        }

        public const float TILE_UPDATE_STEP = 0.1f;

        private float lastTilesUpdate = 0.0f;

        public void Update(float deltaTime)
        {
            lastTilesUpdate += deltaTime;

            if (lastTilesUpdate >= TILE_UPDATE_STEP)
            {
             //   UpdateTiles();

                lastTilesUpdate = 0.0f;
            }

            if (dynamicTiles.Count > 0)
            {
                //TODO: 这里通过拷贝list,因为在dynamic-update过程中dynamic的数量会发生变化
                List<DynamicTile> list = new List<DynamicTile>(dynamicTiles.Values);
                for(int i = 0; i < list.Count; ++i)
                {
                    list[i].Update(deltaTime);
                }
            }
        }

        /*
         * tile在pos点落到地面
         * 触发tile-hitfloor-action
         */
        public void TileHitFloor(IndexPosition worldPos)
        {
            IndexPosition localPos = worldPos - offset;
            ExecuteTileActions(localPos, TileActionRule.ActionType.HIT_FLOOR);
        }

        /*
         * pos点的tile收到了点击
         * 触发tile-clicked-action
         */
        public void TileClicked(IndexPosition worldPos)
        {
            IndexPosition localPos = worldPos - offset;
            ExecuteTileActions(localPos, TileActionRule.ActionType.CLICKED);
        }

        /*
         * tile收到伤害
         * 触发tile-damaged-action
         */
        public void TileDamaged(IndexPosition worldPos)
        {
            IndexPosition localPos = worldPos - offset;
            ExecuteTileActions(localPos, TileActionRule.ActionType.DAMAGED);
        }

        /*
         * 攻击某个pos位置的tile
         * 如果tile存在,使用gameplay来处理tile的伤害
         */
        public bool DamageTile(IndexPosition worldPos, int damage)
        {
            Tile tile = GetTile(worldPos);

            if (tile.tileType != TileDefinition.EMPTY_TILE_TYPE)
            {
                TileDefinition tileDefinition = GetTileDefinition(tile.tileType);
                return world.gameplay.ProcessTileDamage(worldPos, tile, tileDefinition, damage);
            }
            return false;
        }

        /*
         * 销毁某个pos位置的tile
         * 1.将Destroyed标志为设置为true,并且触发tile-destroy-action
         * 2.设置pos位置的tile为empty
         */
        public void DestroyTile(IndexPosition worldPos)
        {
            Tile tile = GetTile(worldPos);
            IndexPosition localPos = worldPos - offset;
            if (tile.tileType != TileDefinition.EMPTY_TILE_TYPE && tile.Destroyed == false)
            {
                tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].Destroyed = true;

                ExecuteTileActions(worldPos, TileActionRule.ActionType.DESTROYED);

                SetTileType(worldPos, TileDefinition.EMPTY_TILE_TYPE);
            }
        }

        /*
         * 更新所有tile
         * 1.更新timout
         * 2.更新updatequeue
         */
        private void UpdateTiles()
        {
            if (enqueueTileUpdates == false)
                return;

            if (pendingTileUpdates.Count > 0 || dynamicTilesTimeout.Count > 0)
            {
                //更新所有timeout，并且触发响应
                if (dynamicTilesTimeout.Count > 0)
                {
                    List<DynamicTile> toExecute = new List<DynamicTile>();

                    //先将所有的timeout更新完然后再执行所有handle,防止其中一个handle操作了其他的timeout,导致迭代器失效
                    {
                        var iter = dynamicTilesTimeout.GetEnumerator();
                        while (iter.MoveNext())
                        {
                            if (--iter.Current.Value.timeout <= 0)
                            {
                                toExecute.Add(iter.Current.Value);
                            }
                        }
                        iter.Dispose();
                    }

                    {
                        var iter = toExecute.GetEnumerator();
                        while(iter.MoveNext())
                        {
                            dynamicTilesTimeout.Remove(iter.Current.tilePosition);
                        }
                        iter.Dispose();
                    }

                    //执行timeout的handle中可以设置其他tile的timeout值，所以我们需要再次验证.
                    {
                        var iter = toExecute.GetEnumerator();
                        while (iter.MoveNext())
                        {
                            if(iter.Current.Dynamic && iter.Current.timeout <= 0)
                            {
                                ExecuteTileActions(iter.Current.tilePosition, TileActionRule.ActionType.TIMEOUT);
                            }
                        }
                        iter.Dispose();
                    }
                }

                //取消入队标志
                {
                    var iter = pendingTileUpdates.GetEnumerator();
                    while(iter.MoveNext())
                    {
                        tiles[iter.Current.x | (iter.Current.y << sizeXbits) | (iter.Current.z << sizeXBitsYBits)].Enqueued = false;
                    }
                    iter.Dispose();
                }
                
                //更换队列,防止handle操作updatequeuew
                if (pendingTileUpdates == pendingTileUpdates1)
                {
                    pendingTileUpdates = pendingTileUpdates2;

                    while (pendingTileUpdates1.Count > 0)
                        UpdateTile(pendingTileUpdates1.Dequeue());
                }
                else
                {
                    pendingTileUpdates = pendingTileUpdates1;

                    while (pendingTileUpdates2.Count > 0)
                        UpdateTile(pendingTileUpdates2.Dequeue());
                }
            }

            ticks++;
        }

        /*
         * 执行pos位置上的tile的updaterules
         */
        private void UpdateTile(IndexPosition localPos)
        {
            IndexPosition worldPos = localPos + offset;
            Tile tile = GetTile(worldPos);

            TileDefinition tileDefinition = GetTileDefinition(tile.tileType);

            if (tileDefinition.tileUpdateRules != null)
            {
                ExecuteTileRules(localPos, tile, tileDefinition.tileUpdateRules.rules);
            }
        }



        //更新top顶点
        private void UpdateTopPosition(IndexPosition localPos, byte type)
        {
            IndexPosition worldPos = localPos + offset;
            int localTop = GetTopPosition(worldPos.x, worldPos.z) - offset.y;

            if (type != TileDefinition.EMPTY_TILE_TYPE)
            {
                if (localTop < localPos.y)
                    topPositions[localPos.x | (localPos.z << sizeXbits)] = (byte)localPos.y;
            }
            else
            {
                if (localTop == localPos.y)
                {
                    localTop = 0;
                    for (int i = localPos.y; i >= 0; i--)
                    {
                        if (GetTileType(new IndexPosition(worldPos.x, i + offset.y, worldPos.z)) != TileDefinition.EMPTY_TILE_TYPE)
                        {
                            localTop = i;
                            break;
                        }
                    }

                    topPositions[localPos.x | (localPos.z << sizeXbits)] = (byte)localTop;
                }
            }
        }

        //获取pos位置的动态tile
        public DynamicTile GetDynamicTile(IndexPosition worldPos)
        {
            return dynamicTiles[worldPos];
        }

        //获取pos位置的tile是否是动态的
        public bool GetTileDynamic(IndexPosition worldPos)
        {
            IndexPosition localPos = worldPos - offset;
            return tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].Dynamic;
        }

        //上报失效的tile
        private void ReportTileInvalidated(IndexPosition localPos, bool lightRelated)
        {
            IndexPosition worldPos = localPos + offset;
            chunk.sectorManager.TileInvalidated(worldPos);
            if (GetTileDynamic(worldPos))
                dynamicTiles[worldPos].Invalidate();
            world.gameplay.TileInvalidated(worldPos, lightRelated);
        }

        //将pos以及周围的6个pos进入更新队列
        private void EnqueueInvalidatedTileAndNearTiles(IndexPosition localPos)
        {
            IndexPosition worldPos = localPos + offset;
            //加入本身
            EnqueueInvalidatedTile(worldPos);

            for(int i = 0; i < (int)Graphics.Faces.Count; ++i)
            {
                IndexPosition newPos = worldPos + Graphics.FACE_DIR_VECTOR[i];
                if(chunk.ContainTilePosition(newPos))
                {
                    EnqueueInvalidatedTile(newPos);
                }
                else
                {
                    Chunk.Chunk nearChunk = chunk.GetNearChunck((Graphics.Faces)i);
                    nearChunk.tileManager.EnqueueInvalidatedTile(newPos);
                }
            }
        }

        /*
         * 设置某个pos的tile的着火状态
         * 1.如果是设置为着火
         *   a.触发tile-onfire-action
         *   b.开启lightSource和关闭CastShadow，更新灯光
         * 2.如果是设置为非着火
         *   a.恢复lightSource和恢复CastShadow，更新灯光
         * 3.上报失效的tile，通知sectorManager,gameplay
         */
        public void SetTileOnFire(IndexPosition worldPos, bool onFire)
        {
            IndexPosition localPos = worldPos - offset;
            if (GetTileType(worldPos) != TileDefinition.EMPTY_TILE_TYPE)
            {
                if (tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].OnFire != onFire)
                {
                    tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].OnFire = onFire;

                    if (onFire)
                    {
                        ExecuteTileActions(localPos, TileActionRule.ActionType.ONFIRE);

                        if (tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].LightSource == false)
                        {
                            tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].LightSource = true;

                            if (tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].CastShadow)
                            {
                                tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].CastShadow = false;

                                //TODO: 光照
                                //if (updateLighting)
                                //    LightModelAmbient.UpdateLuminanceDark(this, pos);
                            }

                            //TODO: 光照
                            //if (updateLighting)
                            //    LightModelLightSource.UpdateLuminanceLight(this, pos, (byte)(Tile.MAX_LUMINANCE - 1));
                            //else
                            SetTileLightSourceLuminance(worldPos, (byte)(Tile.MAX_LUMINANCE - 1));
                        }
                    }
                    else
                    {
                        TileDefinition def = GetTileDefinition(GetTileType(worldPos));

                        if (tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].LightSource != (def.lightSourceIntensity > 0))
                        {
                            //TODO: 光照
                            //if (updateLighting)
                            //    LightModelLightSource.UpdateLuminanceDark(this, pos);

                            tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].LightSource = false;

                            if (def.castShadow != tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].CastShadow != def.castShadow)
                            {
                                tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].CastShadow = false;

                                //TODO: 光照
                                //if (updateLighting)
                                //    LightModelAmbient.UpdateLuminanceLight(this, pos, GetTileAmbientLuminance(pos));
                            }
                        }
                    }

                    if (enqueueTileUpdates)
                        EnqueueInvalidatedTileAndNearTiles(localPos);

                    if (reportTileInvalidated)
                        ReportTileInvalidated(localPos, false);
                }
            }
        }


        //获取pos点tile的着火情况
        public bool GetTileOnFire(IndexPosition worldPos)
        {
            IndexPosition localPos = worldPos - offset;
            return tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].OnFire;
        }

        // 设置Pos点的tile的能量值,上报失效的tile，通知sectorManager,gameplay
        public void SetTileEnergy(IndexPosition worldPos, byte energy)
        {
            IndexPosition localPos = worldPos - offset;
            tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].Energy = energy;

            if (reportTileInvalidated)
                ReportTileInvalidated(localPos, false);
        }

        //获取pos点的tile的能量值
        public byte GetTileEnergy(IndexPosition worldPos)
        {
            IndexPosition localPos = worldPos - offset;
            return tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].Energy;
        }

        //将该点进Update队列
        public void EnqueueInvalidatedTile(IndexPosition worldPos)
        {
            Debug.Assert(chunk.ContainTilePosition(worldPos));

            IndexPosition localPos = worldPos - offset;

            if (tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].Enqueued == false)
            {
                tiles[localPos.x | (localPos.y << sizeXbits) | (localPos.z << sizeXBitsYBits)].Enqueued = true;

                pendingTileUpdates.Enqueue(localPos);
            }
        }

        //执行某个Pos的tile对应的actiontype的rules
        private bool ExecuteTileActions(IndexPosition localPos, TileActionRule.ActionType actionType)
        {
            IndexPosition worldPos = localPos + offset;
            TileDefinition tileDefinition = GetTileDefinition(GetTileType(worldPos));

            if (tileDefinition.tileActionRules != null && tileDefinition.tileActionRules.GetRulesForAction(actionType) != null)
            {
                TileActionRule actionRules = tileDefinition.tileActionRules.GetRulesForAction(actionType);

                ExecuteTileRules(localPos, GetTile(worldPos), actionRules.rules);

                return true;
            }

            return false;
        }
        //执行rules,如果tiletype中途发生变化就直接break
        private void ExecuteTileRules(IndexPosition localPos, Tile tile, List<TileRule> rules)
        {
            IndexPosition worldPos = localPos + offset;
            for (int i = 0; i < rules.Count; ++i)
            {
                if (rules[i].CheckConditions(this, tile, worldPos))
                {
                    rules[i].Execute(this, tile, worldPos);

                    if (GetTileType(worldPos) != tile.tileType)
                        break;
                }
            }
        }

        //将有updaterules的tile全部加入updatequeue
        private void EnqueueTilesWithRules()
        {
            bool[] mapTileDefinitionHasRule = new bool[byte.MaxValue];

            for(int i = 0; i < tileDefinitions.Length; ++i)
            {
                mapTileDefinitionHasRule[tileDefinitions[i].tileType] = (tileDefinitions[i].tileUpdateRules != null);
            }

            for (int x = 0; x < sizeX; x++)
            {
                for (int y = 0; y < sizeY; y++)
                {
                    for (int z = 0; z < sizeZ; z++)
                    {
                        IndexPosition worldPos = new IndexPosition(x + offset.x, y + offset.y, z + offset.z);
                        byte tileType = GetTileType(worldPos);

                        if (mapTileDefinitionHasRule[tileType])
                            EnqueueInvalidatedTile(worldPos);
                    }
                }
            }
        }

        //清空
        public void Clear()
        {
            var iter = dynamicTiles.GetEnumerator();
            while(iter.MoveNext())
            {
                iter.Current.Value.Clear();
            }
            iter.Dispose();

            tiles = null;
            tileDefinitions = null;
            topPositions = null;
            dynamicTiles = null;

            pendingTileUpdates = null;
            pendingTileUpdates1 = null;
            pendingTileUpdates2 = null;
        }


    }
}
